#include "PhysxWorld.h"
#include "IObject.h"


PhysxWorld::PhysxWorld(void)
{
	myOutputStream = new MyOutputStream();
	gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION, NULL, myOutputStream  );
	assert(gPhysicsSDK);
#ifdef _DEBUG
	gPhysicsSDK ->getFoundationSDK().getRemoteDebugger()->connect ("localhost", 5425);    
#endif
	gUtilLib =  NxGetUtilLib();
	assert(gUtilLib);
	gCooking = NxGetCookingLib(NX_PHYSICS_SDK_VERSION);
	assert(gUtilLib);
	CookingInitialized = false;

	gManager = NxCreateControllerManager(NxGetPhysicsSDKAllocator());
	assert(gManager );
}

void PhysxWorld::Initialization(void)
{
	NxSceneDesc sdesc;
	sdesc.gravity.set(0,-0.098f,0);	 ///quase sem gravidade
	scene = gPhysicsSDK->createScene(sdesc);
	assert(scene);
	callBack = new TriggerCallback();
	scene->setUserTriggerReport(callBack);
}


void PhysxWorld::PreUpdate(DWORD timeElapsed)
{
	scene->simulate(timeElapsed);
	scene->flushStream();		
}

void PhysxWorld::PosUpdate(DWORD timeElapsed)
{
	scene-> fetchResults(NX_RIGID_BODY_FINISHED, true);
}

PhysxWorld::~PhysxWorld(void)
{
	NxReleaseControllerManager(gManager);
	gPhysicsSDK->release();
	delete myOutputStream ;
}

void PhysxWorld::AddObject(IObject* obj)
{
	PhysxObject* phyo = (PhysxObject*) obj->GetPhysicObject();	
	assert(phyo);
	switch(phyo->physxObjectType)
	{
		case PhysxObjectType::Actor:
		{
			PhysxActor* actor = (PhysxActor*)phyo;
			assert(actor);
			actor->actor = scene->createActor(actor->actorDescription);
			assert(actor->actor);
			actor->actor->userData = obj;
			///!!!!

			break;
		}
		case PhysxObjectType::DUMMY:
			break;
	}
}
void PhysxWorld::RemoveObject(IObject* obj)
{
	PhysxObject* phyo = (PhysxObject*) obj->GetPhysicObject();	
	switch(phyo->physxObjectType)
	{
		case PhysxObjectType::Actor:
		{
			PhysxActor* actor = (PhysxActor*)phyo;
			assert(actor);
			assert(actor->actor);
			actor->actor->userData = NULL;
			scene->releaseActor(*actor->actor);
			///!!!!
			break;
		}
		case PhysxObjectType::DUMMY:
			break;
	}
}

void PhysxWorld::AddTrigger(Trigger* obj) 
{
	PhysxTrigger* phy = (PhysxTrigger*) obj;	
	assert(phy);
	assert(phy->actorDescription.flags & NX_TRIGGER_ENABLE);
	phy->actor = scene->createActor(phy->actorDescription);
	assert(phy->actor);
	phy->actor->userData = obj;
	
}
void PhysxWorld::RemoveTrigger(Trigger* obj)
{
	PhysxTrigger* phy = (PhysxTrigger*) obj;	
	assert(phy);
	assert(phy->actor);
	phy->actor->userData = NULL;
	scene->releaseActor(*phy->actor);		
}